import os
import math
import xlwings as xw
import matplotlib.pyplot as plt
from utils.border import get_border
from utils.intersection import get_intersection
from utils.fit import get_tangent
from PySide6.QtCore import QThread, Signal


class Worker(QThread):
    finish_sig = Signal()
    progress_sig = Signal(int)

    def __init__(self):
        super(Worker, self).__init__()
        self.names = []
        self.path = ''
        self.indexes = None
        self.hl = 0
        self.fit_args = None

    def set_args(self, image_names, output_path, indexes, horizontal_line, fit_args):
        self.names = image_names
        self.path = output_path
        self.indexes = indexes
        self.hl = horizontal_line
        self.fit_args = fit_args

    def run(self):
        self.progress_sig.emit(0)
        # 导出excel和图像
        excel_name = '角度-厚度.xlsx'
        if not os.path.exists(os.path.join(self.path, excel_name)):
            # 如果Excel不存在，则先新建一个
            wb = xw.Book()
            wb.save(os.path.join(self.path, excel_name))
            wb.close()
        # 打开Excel程序
        wb = xw.Book(os.path.join(self.path, excel_name))
        sheet = wb.sheets["sheet1"]
        sheet.range('A1').value = '角度'
        sheet.range('B1').value = '厚度'
        std_height = 7.0
        for index, name in enumerate(self.names):
            plt.close()
            self.progress_sig.emit(int(index / len(self.names) * 100))
            # 所有计算按照原始图像尺寸进行，写入图片时再进行修改和缩放
            border_x, border_y, img_w, img_h = get_border(name, False)
            # 缩放倍数
            scale = img_h / std_height
            # 计算水平线与曲线的交点
            intersections = get_intersection(zip(border_x, border_y), 0, self.hl * scale)
            if len(intersections) >= 1:
                if len(intersections) >= 2:
                    x, y = intersections[1]
                else:
                    x, y = intersections[0]
                # 计算切线
                top, bottom, left, right, poly_num = self.fit_args
                k, b = get_tangent(zip(border_x, border_y), (x, y),
                                   (top * scale, bottom * scale, left * scale, right * scale), poly_num)
                # 切线不可能90度或0度
                # 计算垂线
                kk = -1 / k
                bb = y - kk * x
                plt.scatter(x / scale, y / scale, c='#000000')
                plt.plot([0, img_w / scale], [b / scale, (k * img_w + b) / scale], 'b')
                plt.plot([0, img_w / scale], [bb / scale, (kk * img_w + bb) / scale], 'y')
                # 计算垂线与曲线的交点
                _intersections = get_intersection(zip(border_x, border_y), kk, bb)
                if len(_intersections) >= 2:
                    _x, _y = _intersections[0]
                    if math.fabs(_x - x) < 3 and math.fabs(_y - y) < 3:  # 修正
                        _x, _y = _intersections[1]
                    plt.scatter(_x / scale, _y / scale, c='#000000')
                    # 实时显示角度和厚度
                    sheet.range('A{}'.format(self.indexes[0] + index + 1)).value = str(math.atan2(kk, 1) * 180 / math.pi)
                    sheet.range('B{}'.format(self.indexes[0] + index + 1)).value = str(math.dist((x, y), (_x, _y)) / scale)
            plt.scatter(border_x / scale, border_y / scale, c='g', s=0.01)
            plt.plot([0, std_height], [self.hl, self.hl], 'r')
            plt.axis((0.0, std_height, 0.0, std_height))
            plt.savefig(os.path.join(self.path, '{}.png'.format(self.indexes[0] + index)))
        # Excel保存
        wb.save()
        wb.app.kill()
        # 处理完成发送信号
        self.finish_sig.emit()
        self.progress_sig.emit(100)
